package com.weimob.demo.configuration;

import java.util.Map;

import javax.servlet.Filter;

import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.RememberMeManager;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;

import com.google.common.collect.Maps;
import com.weimob.demo.admin.security.MyFormAuthenticationFilter;
import com.weimob.demo.admin.security.SystemAuthorizingRealm;
import com.weimob.demo.common.shiro.session.CacheSessionDAO;

/**
 * Created by lenovo on 2016/12/30.
 */
@Configuration
public class ShiroConfiguration {
		
//    @SuppressWarnings("serial")
//	private static Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(){{
//		put("/**.ico", "anon");
//		put("/**", "user");
//        put("/login", "formAuthc");
//        put("/logout", "logout");
//    }};

    private static Map<String, Filter> mapFilter = Maps.newLinkedHashMap();

    /*
      * 自定义系统缓存管理器
      */
    @Bean(name = "appEhCacheCacheManager")
    public EhCacheCacheManager ehCacheCacheManager(EhCacheManagerFactoryBean bean){
        return new EhCacheCacheManager (bean.getObject ());
    }

    /*
     * 据shared与否的设置,Spring分别通过CacheManager.create()或new CacheManager()方式来创建一个ehcache基地.
     */
    @Bean
    public EhCacheManagerFactoryBean ehCacheManagerFactoryBean(){
        EhCacheManagerFactoryBean cacheManagerFactoryBean = new EhCacheManagerFactoryBean ();
        cacheManagerFactoryBean.setConfigLocation (
        		new ClassPathResource("cache/ehcache.xml"));
        cacheManagerFactoryBean.setShared (true);
        return cacheManagerFactoryBean;
    }

    @Bean
    public EhCacheManager getEhCacheManager() {
        EhCacheManager cacheManager = new EhCacheManager();
        cacheManager.setCacheManager(ehCacheManagerFactoryBean().getObject());
        return cacheManager;
    }

    /**
     * 保证实现了Shiro内部lifecycle函数的bean执行
     * @return
     */
    @Bean(name="lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    /**
     * AOP式方法级权限检查
     * @return
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
        daap.setProxyTargetClass(true);
        return daap;
    }
    @Bean
    public AuthorizationAttributeSourceAdvisor AuthorizationAttributeSourceAdvisor() {
        AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
        aasa.setSecurityManager(getSecurityManager());
        return new AuthorizationAttributeSourceAdvisor();
    }

    /**
     * 定义Shiro安全管理配置
     * @return
     */
    @Bean(name= "securityManager")
    public DefaultWebSecurityManager getSecurityManager() {
        DefaultWebSecurityManager dsm = new DefaultWebSecurityManager();
        dsm.setCacheManager(getEhCacheManager());
        dsm.setSessionManager(sessionManager());
        dsm.setRealm(systemReam());
        dsm.setRememberMeManager(rememberMeManager());
        return dsm;
    }

    /**
     * 安全认证过滤器
     * @return
     */
    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(
            @Value("${shiro.login.url}") String loginUrl,
            @Value("${shiro.success.url}") String homeUrl,
            @Value("${shiro.filterChainDefinition}") String filterChainDefinitions)  {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        bean.setSecurityManager(getSecurityManager());

        mapFilter.put("formAuthc", formAuthc());

        bean.setFilters(mapFilter);
        bean.setFilterChainDefinitions(filterChainDefinitions.replace(",", "\n"));
//        bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        bean.setLoginUrl(loginUrl);
        bean.setSuccessUrl(homeUrl);
        return bean;
    }


    @Bean
    public SessionDAO sessionDao() {
    	CacheSessionDAO dao = new CacheSessionDAO();
        dao.setActiveSessionsCacheName("shiro-activeSessionCache");
        return dao;
    }

    @Bean
    public DefaultWebSessionManager sessionManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setSessionDAO(sessionDao());
        sessionManager.setGlobalSessionTimeout(360000);
        sessionManager.setSessionIdCookie(getSimpleCookie());
        return sessionManager;
    }


    @Bean
    public RememberMeManager rememberMeManager() {
        RememberMeManager rememberMe = new CookieRememberMeManager();
        return rememberMe;
    }


    /**
     * 指定本系统SESSIONID, 默认为: JSESSIONID 问题: 与SERVLET容器名冲突, 如JETTY, TOMCAT 等默认JSESSIONID,
     * 当跳出SHIRO SERVLET时如ERROR-PAGE容器会为JSESSIONID重新分配值导致登录会话丢失!
     * @return
     */
    @Bean
    public SimpleCookie getSimpleCookie() {
        SimpleCookie cookie = new SimpleCookie("weimob.session.id");
        cookie.setHttpOnly(true);
        return cookie;
    }



    /**
     * 登录过滤器
     * @return
     */
    @Bean
    public MyFormAuthenticationFilter formAuthc() {
        return new MyFormAuthenticationFilter();
    }

    @Bean
    public SystemAuthorizingRealm systemReam() {
        return new SystemAuthorizingRealm();
    }

}
